package com.iretailer.report.web.business;

import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.iretailer.report.base.BaseAction;
import com.iretailer.report.common.InternationalMessage;
import com.iretailer.report.dto.*;
import com.iretailer.report.easyexcel.data.CameraData;
import com.iretailer.report.easyexcel.listener.CameraDataListener;
import com.iretailer.report.model.Camera;
import com.iretailer.report.model.CameraTypeCount;
import com.iretailer.report.model.Malls;
import com.iretailer.report.model.User;
import com.iretailer.report.util.RMap;
import com.iretailer.report.util.SecurityUserUtil;
import com.iretailer.report.util.StringUtil;
import com.iretailer.report.util.TimeUtil;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.tool.xml.XMLWorkerFontProvider;
import com.itextpdf.tool.xml.XMLWorkerHelper;
import freemarker.template.Configuration;
import freemarker.template.Template;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.archivers.ArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Auther Bennie
 * @Date 2020/6/15 15:47
 * @Description
 */
@Slf4j
@RestController
public class CameraController extends BaseAction {

    private final Configuration configuration;
//    private final ImportCamera importCamera;

    public CameraController(Configuration configuration) {
        this.configuration = configuration;
    }

    @RequestMapping("/business/importCameraExcelData.action")
    public Map<String, Object> importUserExcelData(@RequestParam("file") MultipartFile file, HttpServletRequest request) {
        User principal = SecurityUserUtil.currentUser(request);
        String language = principal.getLanguage();
        if (file == null || file.isEmpty()) {
            return RMap.error(InternationalMessage.EMPTY_UPLOAD_FILE.getByLanguage(language));
        }
        InputStream inputStream;
        try {
            inputStream = file.getInputStream();
        } catch (IOException e) {
            e.printStackTrace();
            return RMap.error(InternationalMessage.FAILED_UPLOAD_FILE.getByLanguage(language));
        }
//        cameraZoneService
        CameraDataListener cameraDataListener = new CameraDataListener(request);
        try {
            EasyExcel.read(inputStream, CameraData.class, cameraDataListener).sheet().doRead();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return RMap.error(e.getMessage());
        }
        return RMap.ok(cameraDataListener.getCameraDataList());
    }

    @RequestMapping("/business/userCameraGrid.action")
    public Map<String, Object> userCameraGrid(@RequestBody ReCamera reCamera, HttpServletRequest request) {
        User user = SecurityUserUtil.currentUser(request);
        QueryOption queryOption = modelMapper.map(reCamera, QueryOption.class);
        String userId = user.getId();
        if (user.getRoleId().equals("-")) {
            userId = null;
        }
        PageResult result = cameraService.grid(userId, reCamera.getEnabled(), null, reCamera.getMallName(), reCamera.getDeviceId(), queryOption);
        return RMap.ok(result);
    }

    @RequestMapping("/business/userCameraStatus.action")
    public Map<String, Object> userCameraStatus(@RequestBody ReCamera reCamera, HttpServletRequest request) {
        User user = SecurityUserUtil.currentUser(request);
        QueryOption queryOption = modelMapper.map(reCamera, QueryOption.class);
        String userId = user.getId();
        if (user.getRoleId().equals("-")) {
            userId = null;
        }
        PageResult result = cameraService.grid(userId, 1, reCamera.getCameraStatus(), reCamera.getMallName(), reCamera.getDeviceId(), queryOption);
        return RMap.ok(result);
    }


    @RequestMapping("/business/saveOrUpdateCamera.action")
    public Map<String, Object> saveOrUpdateCamera(@RequestBody ReCamera reCamera, HttpServletRequest request) {
        User user = SecurityUserUtil.currentUser(request);
        Camera camera = modelMapper.map(reCamera, Camera.class);
        Camera findCamera = cameraService.getOne(new QueryWrapper<Camera>().lambda().eq(Camera::getDeviceId, camera.getDeviceId()));
        if (findCamera != null) {
            if (camera.getId() != null && camera.getId() <= 0) {
                return RMap.error(RMap.Code.DATAREPETITION, "deviceid_can_not_be_repeated");
            } else {
                if (!findCamera.getId().equals(camera.getId())) {
                    return RMap.error(RMap.Code.DATAREPETITION, "deviceid_can_not_be_repeated");
                }
            }
        }
        boolean result = cameraService.saveOrUpdateCamera(camera, reCamera.getCameraZones(), user.getName());
        return RMap.resultBoolean(result);

    }

    @RequestMapping("/business/deleteCamera.action")
    public Map<String, Object> deleteCamera(@RequestBody List<Long> ids) {
        boolean result = cameraService.deleteCamera(ids);
        if (result) {
            return RMap.ok();
        } else {
            return RMap.error(RMap.Code.CONNECTED, "associated_with_physical_regions ");
        }
    }

    @RequestMapping("/business/getCameraTypeCount.action")
    public Map<String, Object> getCameraTypeCount(@RequestBody ReCamera reCamera) {
        if (StringUtil.notEmpty(reCamera.getCompanyId())) {
            List<CameraTypeCount> cameraTypeCounts = cameraService.getCameraTypeCount(reCamera.getCompanyId());
            return RMap.ok(cameraTypeCounts);
        } else {
            return RMap.error();
        }
    }

//    @RequestMapping("/business/uploadCamera.action")
//    public Map<String, Object> upload(MultipartFile file) {
//        try {
//            CameraDataListener listener = new CameraDataListener();
//            EasyExcel.read(file.getInputStream(), CameraData.class, listener).sheet().doRead();
//            List<CameraData> data = listener.getCameraDataList();
//            importCamera.excelAnalysis(data);
//            return RMap.ok();
//        } catch (Exception e) {
//            log.error(e.getMessage(), e);
//            return RMap.error(e.getMessage());
//        }
//    }

    @RequestMapping("/business/download.action")
    public void export(@RequestBody DownloadPdf downloadPdf, HttpServletResponse response) {
        response.setContentType("application/octet-stream;charset=utf-8");
        response.setHeader("Content-disposition", "attachment;filename= " + "hello.zip");
        ServletOutputStream servletOutputStream = null;
        ZipArchiveOutputStream zous = null;
        try {
            servletOutputStream = response.getOutputStream();
            zous = new ZipArchiveOutputStream(servletOutputStream);
            Template template = configuration.getTemplate("pdf/pdf.ftl");
            List<String> mallIds = downloadPdf.getMalls().stream().map(e -> e.getId()).collect(Collectors.toList());

            List<Camera> cameras = cameraService.list(new QueryWrapper<Camera>().lambda().in(Camera::getMallId, mallIds));

            Map<String, List<Camera>> cameraMap = cameras.stream().collect(Collectors.groupingBy(Camera::getMallId));
            List<PdfTemplate> templates = new ArrayList<>();
            for (Malls m : downloadPdf.getMalls()) {
                PdfTemplate t = new PdfTemplate();
                t.setIssueDate(TimeUtil.localDate_format(LocalDate.now(), "yyyy/MM/dd"));
                t.setCompanyName(downloadPdf.getCompanyName());
                t.setMallName(m.getName());
                if (StringUtil.notEmpty(m.getContractStartDate())) {
                    t.setContractStartDate(m.getContractStartDate().replaceAll("-", "/"));
                } else {
                    t.setContractStartDate("");
                }
                if (StringUtil.notEmpty(m.getContractEndDate())) {
                    t.setContractEndDate(m.getContractEndDate().replaceAll("-", "/"));
                } else {
                    t.setContractEndDate("");
                }
                List<Camera> c = cameraMap.get(m.getId());
                if (c != null && c.size() > 0) {
                    t.setDeviceCount(c.size());
                    List<Map<String, Object>> camerasMap = new ArrayList<>();
                    c.stream().sorted(Comparator.comparing(Camera::getDeviceId)).forEach(it -> {
                        Map<String, Object> map = new HashMap<>();
                        map.put("deviceId", it.getDeviceId());
                        if (it.getCreateTime() != null) {
                            map.put("createTime", TimeUtil.localDateTime_format(it.getCreateTime(), "yyyy/MM/dd"));
                        } else {
                            map.put("createTime", "");
                        }
                        camerasMap.add(map);
                    });

                    t.setCameras(camerasMap);
                } else {
                    t.setDeviceCount(0);
                    t.setCameras(Collections.emptyList());
                }
                t.setPublisher("MightyCube");
                templates.add(t);
                PdfTemplate g = (PdfTemplate) t.clone();
                g.setPublisher("高千穂交易(株)");
                templates.add(g);
            }
            for (PdfTemplate p : templates) {
                String html = FreeMarkerTemplateUtils.processTemplateIntoString(template, p);
                byte[] pdf = getPdfByte(html);
                ArchiveEntry entry = new ZipArchiveEntry(p.getPublisher() + "_" + p.getMallName().trim() + ".pdf");
                zous.putArchiveEntry(entry);
                zous.write(pdf);
                zous.closeArchiveEntry();
            }


        } catch (Exception e) {
            log.error(e.getMessage(), e);
        } finally {
            try {
                if (zous != null) {
                    zous.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (servletOutputStream != null) {
                    servletOutputStream.close();
                }
            } catch (IOException e) {
                log.error(e.getMessage(), e);
            }
        }
    }

    private byte[] getPdfByte(String html) throws DocumentException, IOException {
        Document document = new Document(PageSize.A4);
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        PdfWriter writer = PdfWriter.getInstance(document, out);
        document.open();
//        String classpath = CameraController.class.getClassLoader().getResource("").getPath();
//        if (classpath.indexOf("classes!") > 0) {
//            classpath = classpath.replace("classes!", "classes");
//        }
//        String fontpath = classpath + "fonts";
//        log.error("--- " + fontpath);
        XMLWorkerHelper.getInstance().parseXHtml(writer, document,
                new ByteArrayInputStream(html.getBytes("UTF-8")),
                XMLWorkerHelper.class.getResourceAsStream("/default.css"),
                Charset.forName("UTF-8"),
                new XMLWorkerFontProvider());
        document.close();
        return out.toByteArray();
    }

}
